﻿// -----------------------------------------------------------------------
// <copyright file="Grammar.cs" company="ISPU">
// Grammar of JavaScript.
// Created by alexander.kiselev 2/27/2012
// </copyright>
// -----------------------------------------------------------------------

namespace JavaScript8000.Parser
{
    using System;
    using System.Collections.Generic;
    using System.Text;

    /// <summary>
    /// Grammar of JavaScript.
    /// </summary>
    public static class Grammar
    {
        /// <summary>
        /// dictionary of rules.
        /// </summary>
        private static Dictionary<string, List<string>> rules;

        /// <summary>
        /// Gets the form with grammar.
        /// </summary>
        private static BrainFuck form;

        /// <summary>
        /// Gets the form.
        /// </summary>
        /// <returns>
        /// Form with grammar.
        /// </returns>
        public static BrainFuck GetForm()
        {
            if (form == null || form.IsDisposed)
            {
                form = new BrainFuck();
            }
            return form;
        }

        /// <summary>
        /// Gets the rule.
        /// </summary>
        /// <param name="ruleName">Name of the rule.</param>
        /// <returns>List of string which represent tokens of rule.</returns>
        public static List<string> GetRule(string ruleName)
        {
            List<string> result;
            if (rules.TryGetValue(ruleName, out result))
            {
                return result;
            }

            // Return null if we can't find the rule.
            return null;
        }

        /// <summary>
        /// Initializes this instance.
        /// </summary>
        public static void Initialyze()
        {
            rules = new Dictionary<string, List<string>>();

            StringBuilder currentToken = new StringBuilder();
            List<string> currentRule = null;
            string source = Properties.Resources.Grammar;

            // Read grammar and parse rules.
            for (int i = 0; i < source.Length; i++)
            {
                bool wasAdded = false;
                if (source[i] != ' ' && source[i] != '\r' && source[i] != '\t' && source[i] != '\n')
                {
                    currentToken.Append(source[i]);
                    wasAdded = true;
                }

                if (!wasAdded || i == source.Length - 1)
                {
                    if (currentToken.Length > 0)
                    {
                        string token = currentToken.ToString();
                        currentToken.Clear();

                        if (currentRule == null)
                        {
                            if (token == ";" || token == "=")
                            {
                                throw new InvalidOperationException("Wrong rule name.");
                            }

                            // Create new rule.
                            currentRule = new List<string>();
                            rules.Add(token, currentRule);
                        }
                        else if (token == ";")
                        {
                            // Close current rule.
                            currentRule = null;
                        }
                        else if (token != "=")
                        {
                            // Who care about equals sign =).
                            // Add new token to rule.
                            currentRule.Add(token);
                        }
                        else if (currentRule.Count > 0)
                        {
                            throw new InvalidOperationException("Equals sign was not after rule name.");
                        }
                    }
                }
            }
        }
    }
}
